﻿using FilmBlowingMachine.Winform.Lib;
using FilmBlowingMachine.Winform.PLC;
using System;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FilmBlowingMachine.Winform
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public DeltaAs200 AS200 { get; set; }

        public int UpdateUI(CancellationToken token)
        {
            Console.WriteLine($"UpdateUI thread id:{Thread.CurrentThread.ManagedThreadId}");
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    return -1;
                }

                try
                {
                    if (!(AS200?.IsConnected ?? false))
                    {
                        Thread.Sleep(TimeSpan.FromSeconds(0.3));
                        continue;
                    }

                    ServoHomingBtn.BackColor = AS200.Homing ? Color.Green : Color.Gray;
                    HomingFlagLabel.BackColor = AS200.HomingFlag ? Color.Green : Color.Gray;
                    HomingFinishedLabel.BackColor = AS200.HomingFinished ? Color.DarkGreen : Color.Red;
                    RunningLabel.BackColor = AS200.Running ? Color.Green : Color.Red;

                    SetTextBox(HomingFastFreqTextbox, AS200.HomingFastFreq.ToString());
                    SetTextBox(HomingLowFreqTextbox, AS200.HomingLowFreq.ToString());
                    SetTextBox(PulsePerMillTextbox, AS200.PulsePerMill.ToString());
                    SetTextBox(FilmLengthTextbox, AS200.FilmWidth.ToString());
                    SetTextBox(AutoFreqTextbox, AS200.AutoFreq.ToString());
                    SetTextBox(MeasuringServoCurrentPosTextbox, AS200.MeasuringServoCurrentPosition.ToString());
                    SetTextBox(SamplingStartAddrTextBox, AS200.SlampingStartPosition.ToString());
                    SetTextBox(SamplingEndAddrTextBox, AS200.SlampingEndPosition.ToString());
                    SetTextBox(SamplingDelayTextBox, AS200.SlampingDelayTime.ToString());
                    SetTextBox(FirstFilmTextBox, AS200.FirstSamplingFilmLength.ToString());
                    SetTextBox(SecondFilmTextBox, AS200.SecondSamplingFilmLength.ToString());
                    SetTextBox(CurFilmLengthTextBox, AS200.CurrentFilmLength.ToString());
                    SetTextBox(CurAngleTextBox, AS200.CurrentAngle.ToString());
                    Thread.Sleep(200);
                }
                catch (Exception ex)
                {
                }
            }
        }

        // 后台线程更新TextBox
        private void SetTextBox(TextBox txt, string value)
        {
            Action act = () =>
            {
                if (!txt.Focused)
                {
                    txt.Text = value;
                }
            };

            if (txt.InvokeRequired)
            {
                txt.BeginInvoke(act);
            }
            else
            {
                act();
            }
        }

        /// <summary>
        /// 线程2
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public int RecordLength(CancellationToken token)
        {
            Console.WriteLine($"RecordLength thread id:{Thread.CurrentThread.ManagedThreadId}");
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    return -1;
                }

                if (!(AS200?.IsConnected ?? false))
                {
                    Thread.Sleep(TimeSpan.FromSeconds(0.5));
                    continue;
                }

                try
                {
                    AS200.RecordLengthAnglePairs();
                    Thread.Sleep(1);
                }
                catch (Exception)
                {

                }
            }
        }
        
        /// <summary>
        /// 断线重连
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public int KeepAlive(CancellationToken token)
        {
            Console.WriteLine($"KeepAlive thread id:{Thread.CurrentThread.ManagedThreadId}");
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    return -1;
                }

                AS200.KeepAlive();

                Thread.Sleep(TimeSpan.FromSeconds(0.5));
            }
        }
        private bool ValidateInt(KeyPressEventArgs e)
        {
            if (e.KeyChar != '\b' && !Char.IsDigit(e.KeyChar))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private bool ValidateFloat(KeyPressEventArgs e)
        {
            if (e.KeyChar != '\b' && !Char.IsDigit(e.KeyChar) && e.KeyChar != '.')
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private void HomingLowFreqTextbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (int.TryParse(HomingLowFreqTextbox.Text, out int res))
                {
                    AS200.HomingLowFreq = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateInt(e);
        }

        private void AutoFreqTextbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (int.TryParse(AutoFreqTextbox.Text, out int res))
                {
                    AS200.AutoFreq = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateInt(e);
        }

        private void PulsePerMillTextbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (float.TryParse(PulsePerMillTextbox.Text, out float res))
                {
                    AS200.PulsePerMill = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateFloat(e);
        }

        private void ServoHomingBtn_MouseDown(object sender, MouseEventArgs e)
        {
            AS200.Homing = true;
        }

        private void ServoHomingBtn_MouseUp(object sender, MouseEventArgs e)
        {
            AS200.Homing = false;
        }

        private void GetMeasuringPointsBtn_Click(object sender, EventArgs e)
        {
            // dgv1
            AS200.GetMeasuringPoints();
            MeasuringPointGDV.DataSource = AS200.MeasuringPoints;

            // dgv2
            LenAngleRecordNumTextBox.Text = AS200.LengthAnglePairs.Count.ToString();
            KeyValueDgv.DataSource = AS200.LengthAnglePairs.ToList();
        }

        private void HomingFastFreqTextbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (int.TryParse(HomingFastFreqTextbox.Text, out int res))
                {
                    AS200.HomingFastFreq = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateInt(e);
        }

        private void Textbox2Int()
        {
        }

        private void FilmLengthTextbox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (float.TryParse(FilmLengthTextbox.Text, out float res))
                {
                    AS200.FilmWidth = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateFloat(e);
        }

        private void FilterDataBtn_Click(object sender, EventArgs e)
        {
        }

        private void GetLengthAnglePairsBtn_Click(object sender, EventArgs e)
        {
            LenAngleRecordNumTextBox.Text = AS200.LengthAnglePairs.Count.ToString();
            MeasuringPointGDV.DataSource = AS200.LengthAnglePairs.ToList();
        }

        CancellationTokenSource cts;
        Task[] tasks = new Task[3];
        private void ConnectBtn_Click(object sender, EventArgs e)
        {
            ConnectBtn.Enabled = false;
            if (!IPAddress.TryParse(PLCIPAddressTextbox.Text, out IPAddress ip))
            {
                MessageBox.Show("IP不合法！");
                return;
            }

            try
            {
                if (AS200 == null)
                {
                    AS200 = new DeltaAs200(ip.ToString(), 502, 120);
                }

                if (AS200.IsConnected)
                {
                    cts?.Cancel();
                    Task.WaitAll(tasks);

                    if (AS200.Disconnect())
                    {
                        ConnectBtn.Text = "连 接";
                        PLCIPAddressTextbox.Enabled = true;
                    }
                }
                else
                {
                    if (!AS200.Connect())
                    {
                        MessageBox.Show("PLC连接失败.");
                    }
                    else
                    {
                        cts = new CancellationTokenSource();
                        tasks[0] = Task.Run(() => { UpdateUI(cts.Token); }, cts.Token)
                            .ContinueWith(_ => { Console.WriteLine($"1.UpdateUI is finished."); });
                        tasks[1] = Task.Run(() => { RecordLength(cts.Token); }, cts.Token)
                            .ContinueWith(_ => { Console.WriteLine($"2.RecordLength is finished."); });
                        tasks[2] = Task.Run(() => { KeepAlive(cts.Token); }, cts.Token)
                            .ContinueWith(_ => { Console.WriteLine($"3.KeepAlive is finished."); });

                        ConnectBtn.Text = "断 开";
                        PLCIPAddressTextbox.Enabled = false;
                    }
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("连接失败.");
            }
            ConnectBtn.Enabled = true;
        }

        private void SamplingStartAddrTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (float.TryParse(SamplingStartAddrTextBox.Text, out float res))
                {
                    AS200.SlampingStartPosition = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateFloat(e);
        }

        private void SamplingEndAddrTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (float.TryParse(SamplingEndAddrTextBox.Text, out float res))
                {
                    AS200.SlampingEndPosition = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateFloat(e);
        }

        private void SamplingDelayTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)13)
            {
                if (ushort.TryParse(SamplingDelayTextBox.Text, out ushort res))
                {
                    AS200.SlampingDelayTime = res;
                }
                else
                {
                    MessageBox.Show("数据格式错误。");
                }
            }
            e.Handled = !ValidateInt(e);
        }

        private void JogPBtn_MouseDown(object sender, MouseEventArgs e)
        {
            AS200.JogP = true;
        }

        private void JogPBtn_MouseUp(object sender, MouseEventArgs e)
        {
            AS200.JogP = false;
        }

        private void JogNBtn_MouseDown(object sender, MouseEventArgs e)
        {
            AS200.JogN = true;
        }

        private void JogNBtn_MouseUp(object sender, MouseEventArgs e)
        {
            AS200.JogN = false;
        }

        private void ExportDataBtn_Click(object sender, EventArgs e)
        {
            CSVHelper cSVHelper = new CSVHelper();
            cSVHelper.DataGridViewToCSV(MeasuringPointGDV);
        }

        private void InteractBtn_Click(object sender, EventArgs e)
        {
            AS200.StartSampling(true, false);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            CSVHelper cSVHelper = new CSVHelper();
            cSVHelper.DataGridViewToCSV(KeyValueDgv);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            if (AS200?.IsConnected ?? false)
            {
                toolStripStatusLabel1.Text =  "通讯正常。";
            }
            else
            {
                toolStripStatusLabel1.Text = "连接已断开。";
            }
        }
    }
}